# coding=utf-8

import json

from typing import Dict, List

from ...base.common_define import FRAME_SYNC
from ...rpcserver.push_lib import multicast_msg
from ..user_manager import User
from ...share.espoir_log import global_log as logger


class FrameConfig(object):

    def __init__(self) -> None:
        self.logic_interval: int = 5  # 逻辑帧间隔（多少帧广播一次）
        self.frame_num: int = 60  # 一秒多少帧

    @property
    def frame_interval(self) -> int:
        return int(1000 / self.frame_num)


class BattleStatus(object):
    NOT_START = 0  # 未开始
    STARTING = 1  # 进行中
    END = 2  # 已结束


class FrameServer(object):

    def __init__(self, _id: str, config: FrameConfig) -> None:
        super().__init__()
        self._id: str = _id  # 每场战斗的唯一标识
        self._userIds: List[str] = []  # 参与者
        self._cur_frame_no: int = 0  # 当前逻辑帧号

        # key: frame_no, value: op_list
        self._cache_op: Dict[int, List[Dict]] = {}  # 缓存的操作（两次广播间）
        self._op_log: List[Dict] = []  # 历史操作日志
        self.status: int = 0  # 0: 未开始， 1: 进行中， 2: 已结束

        self._detail: Dict = {}  # 战斗详情
        self.config: FrameConfig = config

    def add_op(self, op: Dict) -> None:
        if self._cur_frame_no not in self._cache_op:
            self._cache_op[self._cur_frame_no] = []
        self._cache_op[self._cur_frame_no].append(op)
        self._op_log.append(op)

    def get_broadcast_info(self) -> Dict:
        return {
            "target_frame_no": self._cur_frame_no,
            "act_records": self._cache_op
        }

    def add_users(self, user_list: List[User]) -> None:
        id_list = [user.user_id for user in user_list]
        self._userIds.extend(id_list)
        self._detail["users"] = user_list

    def clear(self) -> None:
        self._userIds.clear()
        self._detail["users"].clear()

    async def run(self) -> None:
        if self.status != BattleStatus.STARTING:
            return
        if self._cur_frame_no % self.config.logic_interval == 0:
            await self.broadcast()
        self._cur_frame_no += 1

    # 广播操作
    async def broadcast(self) -> None:
        session_ids = [user.session_id for user in self._detail["users"]]
        logger.info("broadcast", session_ids=session_ids,
                    cur_frame_no=self._cur_frame_no, op=self._cache_op)
        await multicast_msg(session_ids, FRAME_SYNC,
                            json.dumps({
                                "act_records": self._cache_op,
                                "target_frame_no": self._cur_frame_no
                            }))
        self._cache_op.clear()
